package service

import (
	"context"
	"fmt"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"io"
	api "module-gin/api/example"
	"sync"
	"time"
)

type ApiService struct {
	api.UnsafeAppExampleHelloServer
}

// HelloRpcGet app rpc and grpc-module-gin get
func (s *ApiService) HelloRpcGet(context.Context, *emptypb.Empty) (*api.AppSrv, error) {
	return &api.AppSrv{
		Message: "HelloRpcGet Success!",
	}, nil
}

// HelloRpcPost app rpc and grpc-module-gin post
func (s *ApiService) HelloRpcPost(context.Context, *api.AppSrv) (*api.AppSrv, error) {
	return &api.AppSrv{
		Message: "HelloRpcPost Success!",
	}, nil
}

// HelloRpcServerStream 服务端 单项数据流
func (s *ApiService) HelloRpcServerStream(req *api.StreamRequest, res api.AppExampleHello_HelloRpcServerStreamServer) error {
	_ = res.SetHeader(metadata.New(map[string]string{
		"test-h": "this is HelloRpcServerStream !",
	}))
	var i int
	for {
		i++
		err := res.SendMsg(&api.StreamRequest{
			Message: fmt.Sprintf("第 %v 次，向客户端传递", i),
		})
		if err != nil {
			return err
		}
		if i >= 5 {
			break
		}
		time.Sleep(time.Second)
	}
	return status.Error(codes.Canceled, "end")
}

// HelloRpcClientStream 客户端 单项数据流
func (s *ApiService) HelloRpcClientStream(req api.AppExampleHello_HelloRpcClientStreamServer) error {
	var wg sync.WaitGroup
	wg.Add(2)
	// 接收
	for {
		if _, err := req.Recv(); err != nil {
			if err == io.EOF {
				fmt.Println("[客户端发送结束]  接收结束~")
				return nil
			}
			e, ok := status.FromError(err)
			if ok && e.Code() == codes.Canceled {
				fmt.Println("[客户端发送结束]  接收结束~")
				return nil
			}
			if err != nil {
				fmt.Println("[客户端数据流] ERROR", err)
				return err
			}
			break
		}
	}
	return nil
}

// HelloRpcAllStream 客户端服务端 双向数据流
func (s *ApiService) HelloRpcAllStream(req api.AppExampleHello_HelloRpcAllStreamServer) error {
	var wg sync.WaitGroup
	wg.Add(2)
	// 接收
	go func() {
		defer wg.Done()
		for {
			if _, err := req.Recv(); err != nil {
				if err == io.EOF {
					fmt.Println("[客户端发送结束]  接收结束~")
				}
				e, ok := status.FromError(err)
				if ok && e.Code() == codes.Canceled {
					fmt.Println("[客户端发送结束]  接收结束~")
				}
				if err != nil {
					fmt.Println("[客户端数据流] ERROR", err)
				}
				break
			}
		}
	}()
	// 发送
	go func() {
		defer wg.Done()
		_ = req.SetHeader(metadata.New(map[string]string{
			"test-h": "this is HelloRpcServerStream !",
		}))
		var i int
		for {
			i++
			err := req.SendMsg(&api.StreamRequest{
				Message: fmt.Sprintf("第 %v 次，向客户端传递", i),
			})
			if err != nil {
				panic(err)
			}
			if i >= 5 {
				break
			}
			time.Sleep(time.Second)
		}
	}()
	wg.Wait()
	return status.Error(codes.Canceled, "end")
}
